type bstmt =
	(*push commands*)
	  Litin of int (* Push a literal *)
	| Litst of string (*push string*)
	| Litsh of string (*push string*)
	
	| Drp (* Discard a value the bytecode interpreter will handle the different types that can be dropped*)
	
	| Bin of Ast.op (* Perform arithmetic on top of stack *)
	
	(*copy of global with id of int to stack top*)
	| Lod of int (* puts global variable on top of stack *)
	
	(*store stack object in global variables given id*)
	| Str of int (* create global variable from top of stack *)
	
	(*these stay the same from micro C*)
	| Lfp of int (* Load frame pointer relative *)
	| Sfp of int (* Store frame pointer relative *)
	| Jsr of int (* Call function by absolute address *)
	| Ent of int (* Push FP, FP -> SP, SP += i *)
	| Rts of int (* Restore FP, SP, consume formals, push result *)
	| Beq of int (* Branch relative if topofstack is zero *)
	| Bne of int (* Branch relative if topofstackis nonzero*)
	| Bra of int (* Branch relative *)
    | Lfpa of int (* This is the start index of this array variable. Index is evaluated and 
					 put on top of stack in an int structure. *)
    | Sfpa of int
    | Loda of int
    | Stra of int
	| Hlt (* Terminate *)
	
	(*these are added for graphic functions*)
	| Sgraph (*create empty graph*)
	| Egraph (* Erase the whole graph *)

	(*prints*)
	
	(*freeze and move commands*)
	| Susp (* Freeze for int milliseconds specified on top of stack*)
	| Movby (* move object on top of stack by the x and y ammounts specified by the two integers on teh stack above it*) 
	| Movto
	(*get specfic value of object*)
	| GetC (*get value specified by int on top of stack *)
	| MakeS (* Take top 5 ints and then make a new shape. from top to bottom: type, v1, v2, v3, v4 *)
	
type prog = {
	size_globals : int; (* Number of global variables *)
	text : bstmt array; (* Code for all the functions *)
}

let string_of_stmt = function 
		Litin(i) -> "Litin " ^ string_of_int i
	| 	Drp		-> "Drp"
	|	Bin(Ast.Add) -> "Add"
	|   Bin(Ast.Sub) -> "Sub"
	|   Bin(Ast.Mult) -> "Mult"
	|   Bin(Ast.Div) -> "Div"
	|   Bin(Ast.Equal) -> "Equal"
	|   Bin(Ast.Neq) -> "Neq"
	|   Bin(Ast.Less) -> "Less"
	|   Bin(Ast.Leq) -> "Leq"
	|   Bin(Ast.Geq) -> "Geq"
	|   Bin(Ast.Greater) -> "Greater"
	|   Lod(i) -> "Lod " ^ string_of_int i
	|   Str(i) -> "Str " ^ string_of_int i
	|   Lfp(i) -> "Lfp " ^ string_of_int i
	|   Sfp(i) -> "Sfp " ^ string_of_int i
	|   Jsr(i) -> "Jsr " ^ string_of_int i
	|   Ent(i) -> "Ent " ^ string_of_int i
	|   Rts(i) -> "Rts " ^ string_of_int i
	|   Bne(i) -> "Bne " ^ string_of_int i
	|   Beq(i) -> "Beq " ^ string_of_int i
	|   Bra(i) -> "Bra " ^ string_of_int i
	|   Litsh(i) -> "Litsh" ^ i
	|   Litst(i) -> "Litst" ^ i
	|   Egraph -> "Egraph"
	|   Sgraph -> "Sgraph"
	|   Hlt -> "Hlt" 
	|   Movto -> "Movto"
	|   Movby -> "Movby"
	|   Susp -> "Susp"
	|   GetC -> "GetC"
    |   MakeS -> "MakeS"
	|	Loda(i) -> "Loda " ^ string_of_int i
	|	Stra(i) -> "Stra " ^ string_of_int i
	|	Lfpa(i) -> "Lfpa " ^ string_of_int i
	|	Sfpa(i) -> "Sfpa " ^ string_of_int i

let string_of_prog p = 
	string_of_int p.size_globals ^ " slots to store global variables\n" ^ 
	let funca = Array.mapi
		(fun i s -> string_of_int i ^ " " ^ string_of_stmt s) p.text
	in String.concat "\n" (Array.to_list funca)
